import { Col } from "./data_ext";
import SerializeAble, { c2n, GetCSIByClass, n2c, Serialize, SerializeClass } from "./serialize";
import Utils from "./utils";

@SerializeClass("LibraryRecord")
export class LibraryRecord extends SerializeAble {
    @Serialize()
    key: string;
};

export class Library {
    private static __inited = false;
    private static __recordMap: Map<{ prototype: LibraryRecord }, Col<LibraryRecord>> = new Map();
    static Init() {
        if (this.__inited) {
            return;
        }
        let allLibJas = Utils.loader.getAssets<cc.JsonAsset>("", "librarys", "cc.JsonAsset");
        allLibJas.forEach(ja => {
            if (typeof ja.json === "object" && ja.json instanceof Array) {
                ja.json.forEach((conf) => {
                    this.__create(conf);
                });
            }
            else {
                this.__create(ja.json);
            }
        });
        this.__inited = true;
    }
    private static __create(json: any) {
        if (!json.key) {
            console.warn("Library 注意: 有配置没有设置key成员", json);
        }
        let ctor = n2c(json["$cn"] || json["__cn"]);
        let conf = new ctor();
        if (!(conf instanceof LibraryRecord)) {
            console.error(`Library 错误: ${c2n(ctor)} 类没有继承 LibraryRecord`);
        }
        conf.assignFromJSON(json);
        if (!this.__recordMap.has(ctor)) {
            this.__recordMap.set(ctor, {});
        }
        this.__recordMap.get(ctor)[json.key] = conf;
    }
    static GetRecord<T extends LibraryRecord>(ctor: { prototype: T }, key: string) {
        if (!this.__inited) {
            this.Init();
        }
        const col = this.__recordMap.get(ctor);
        if (col) {
            return <T>col[key];
        }
        else {
            return null;
        }
    }
    static CloneRecord<T extends LibraryRecord>(ctor: { prototype: T }, key: string) {
        if (!this.__inited) {
            this.Init();
        }
        const conf = this.GetRecord(ctor, key);
        if (conf) {
            return <T>conf.clone();
        }
        else {
            return null;
        }
    }
    // 
    static GetRecords<T extends LibraryRecord>(ctor: { prototype: T }) {
        if (!this.__inited) {
            this.Init();
        }

        let list = [];
        let col = this.__recordMap.get(ctor);
        if (col) {
            for (let key in col) {
                list.push(col[key]);
            }
        }

        return list;
    }

    static SetRecord<T extends LibraryRecord>(record: T) {
        if (!this.__inited) {
            this.Init();
        }
        if (!this.__recordMap.has(record.constructor)) {
            this.__recordMap.set(record.constructor, {});
        }
        this.__recordMap.get(record.constructor)[record.key] = record;
    }
    static getRecordsIncludeChildren<T extends LibraryRecord>(baseCtor: { prototype: T }) {
        let allItemConfig: T[] = [];
        GetCSIByClass(baseCtor).children.forEach(child => {
            allItemConfig = allItemConfig.concat(Library.GetRecords(child.ctor));
        });
        allItemConfig = allItemConfig.concat(Library.GetRecords(baseCtor));
        return allItemConfig;
    }
};

window["library"] = Library;